package com.hq.es.controller;

import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.hq.es.dto.*;
import com.hq.es.utils.ElasticsearchUtil;
import com.hq.es.vo.EsPage;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.get.GetRequest;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.List;
import java.util.Map;

@Api(tags = "文档检索")
@RequestMapping("/documentSearch")
@RestController
@Slf4j
public class DocumentSearchController {

    @Resource
    private ElasticsearchUtil elasticsearchUtil;


    @GetMapping("/termSearch/{index}/{field}/{keyword}")
    @ApiOperation(value = "关键字查询",notes = "对搜索内容不进行分词")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "index",paramType = "path",value = "索引名称",required = true),
            @ApiImplicitParam(name = "field",paramType = "path",value = "查询字段",required = true),
            @ApiImplicitParam(name = "keyword",paramType = "path",value = "关键字",required = true)
    })
    @ApiOperationSupport(order =1)
    public Object termSearch (@PathVariable String index,
                              @PathVariable String field,
                              @PathVariable String keyword) throws IOException {
        return  elasticsearchUtil.termSearch(index,field,keyword);
    }

    @PostMapping("/termsSearch")
    @ApiOperation(value = "多关键字查询")
    @ApiOperationSupport(order = 2)
    public Object termsSearch (@RequestBody TermsSearchDTO termsSearchDTO ) throws IOException {
        return  elasticsearchUtil.termsSearch(termsSearchDTO);
    }


    @GetMapping("/matchQuery/{index}/{field}/{keyword}")
    @ApiOperation(value = "匹配查询",notes = "match query底层会自动转换为term+should/must方式</br>" +
            "  \"query\": {\n" +
            "   \"match\": {\n" +
            "         \"title\": {\n" +
            "            \"query\":    \"java elasticsearch\",\n" +
            "            \"operator\": \"and\"\n" +
            "        }\n" +
            "   }\n" +
            "  }")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "index",paramType = "path",value = "索引名称",required = true),
            @ApiImplicitParam(name = "field",paramType = "path",value = "查询字段",required = true),
            @ApiImplicitParam(name = "keyword",paramType = "path",value = "关键字",required = true)
    })
    @ApiOperationSupport(order = 3)
    public Object matchQuery (@PathVariable String index,
                              @PathVariable String field,
                              @PathVariable String keyword) throws IOException {
        return  elasticsearchUtil.matchQuery(index,field,keyword);
    }


    @PostMapping("pageList/{index}/{pageNo}/{pageSize}/{keyword}")
    @ApiOperation(value = "分页查询")
    @ApiOperationSupport(order = 4)
    public Object pageList(@RequestBody PageSearchDTO pageSearchDTO) throws IOException {
        EsPage esPage = elasticsearchUtil.queryPageList(pageSearchDTO);
        return  esPage;
    }





    @GetMapping("/prefixSearch/{index}/{field}/{prefix}")
    @ApiOperation(value = "前缀查询")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "index",paramType = "path",value = "索引名称",required = true),
            @ApiImplicitParam(name = "field",paramType = "path",value = "查询字段",required = true),
            @ApiImplicitParam(name = "prefix",paramType = "path",value = "前缀词",required = true)
    })
    public Object prefixSearch(@PathVariable String index,
                               @PathVariable String field,
                               @PathVariable String prefix)throws IOException{
        return  elasticsearchUtil.prefixSearch(index,field,prefix);
    }



    @GetMapping("/wildcardSearch/{index}/{field}/{condition}")
    @ApiOperation(value = "通配符查询",notes = "使用wildcard相当于SQL的like，前后都可以拼接*，表示匹配0到多个任意字符")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "index",paramType = "path",value = "索引名称",required = true),
            @ApiImplicitParam(name = "field",paramType = "path",value = "查询字段",required = true),
            @ApiImplicitParam(name = "condition",paramType = "path",value = "查询条件",required = true)
    })
    public Object wildcardSearch(@PathVariable String index,
                               @PathVariable String field,
                               @PathVariable String condition)throws IOException{
        return  elasticsearchUtil.wildcardSearch(index,field,condition);
    }

    @PostMapping("/idsSearch")
    @ApiOperation(value = "多id查询")
    public Object idsSearch(@RequestBody IdsSearchDTO idsSearchDTO)throws IOException{
        return  elasticsearchUtil.idsSearch(idsSearchDTO);
    }



    @GetMapping("/fuzzyQuery/{index}/{field}/{condition}")
    @ApiOperation(value = "模糊查询",notes ="fuzzy 模糊查询  最大模糊错误 必须在0-2之间\n" +
                                           "搜索关键词长度为 2 不允许存在模糊 0\n" +
                                           "搜索关键词长度为3-5 允许一次模糊 0 1 \n" +
                                           "搜索关键词长度大于5 允许最大2模糊")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "index",paramType = "path",value = "索引名称",required = true),
            @ApiImplicitParam(name = "field",paramType = "path",value = "查询字段",required = true),
            @ApiImplicitParam(name = "condition",paramType = "path",value = "查询条件",required = true)
    })
    public Object fuzzyQuery(@PathVariable String index,
                              @PathVariable String field,
                              @PathVariable String condition
                              ) throws IOException {
        return  elasticsearchUtil.fuzzyQuery(index,field,condition);
    }


    @GetMapping("/queryGroupBy/{index}/{field}/{lte}/{gte}")
    @ApiOperation(value = "范围查询")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "index",paramType = "path",value = "索引名称",required = true),
            @ApiImplicitParam(name = "field",paramType = "path",value = "查询字段",required = true),
            @ApiImplicitParam(name = "gte",paramType = "path",value = "大于",required = true),
            @ApiImplicitParam(name = "lte",paramType = "path",value = "小于",required = true)
    })
    public Object rangeSearch(@PathVariable String index,
                              @PathVariable String field,
                              @PathVariable String lte,
                              @PathVariable String gte) throws IOException {
        return  elasticsearchUtil.rangeSearch(index,field,gte,lte);
    }


    @GetMapping("/highlightQuery/{index}/{field}/{condition}")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "index",paramType = "path",value = "索引名称",required = true),
            @ApiImplicitParam(name = "field",paramType = "path",value = "字段名",required = true),
            @ApiImplicitParam(name = "condition",paramType = "path",value = "查询",required = true)
    })
    @ApiOperation(value = "高亮查询")
    public Object highlightQuery( @PathVariable String index,@PathVariable String field,@PathVariable String condition) throws IOException {
        return elasticsearchUtil.highlightQuery(index,field,condition);
    }



    @GetMapping("/autoCompletion")
    @ApiOperation(value = "自动补全查询")
    public Object autoCompletion(String keyword) throws IOException {
        return elasticsearchUtil.autoCompletion(keyword);
    }


    @GetMapping("/boolQueryMust")
    @ApiOperation(value = "boolQuery【must】",notes = "bool 关键字: 用来组合多个条件实现复杂查" +
                                                "</br>must: 相当于&& 同时成立")
    public Object boolQuery(String category,String title) throws IOException {
        return elasticsearchUtil.boolQueryMust(category,title);
    }


    @GetMapping("/boolQueryShould")
    @ApiOperation(value = "boolQuery【should】",notes = "bool 关键字: 用来组合多个条件实现复杂查" +
            "</br>should: 相当于|| 成立一个就行")
    public Object boolQueryShould(String authorName1,String authorName2) throws IOException {
        return elasticsearchUtil.boolQueryShould(authorName1,authorName2);
    }

    @GetMapping("/boolQueryMustNot")
    @ApiOperation(value = "boolQuery【mustnot】",notes = "bool 关键字: 用来组合多个条件实现复杂查" +
            "</br>mustnot: 相当于! 非 不能满足任何一个")
    public Object boolQueryMustNot(String category) throws IOException {
        return elasticsearchUtil.boolQueryMustNot(category);
    }

    @PostMapping("/multiMatchQuery")
    @ApiOperation(value = "多字段查询",notes = "对多个字段内进行检索")
    public Object multiMatchQuery(@RequestBody MultiMatchQueryDTO multiMatchQueryDTO) throws IOException {
        return elasticsearchUtil.multiMatchQuery(multiMatchQueryDTO);
    }



    @GetMapping("/queryGroupBy/{index}/{groupByField}/{size}")
    @ApiOperation(value = "GroupBy查询 聚合查询")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "index",paramType = "path",value = "索引名称",required = true),
            @ApiImplicitParam(name = "groupByField",paramType = "path",value = "分组字段",required = true),
            @ApiImplicitParam(name = "size",paramType = "path",value = "排名前n的分词",required = false)
    })
    public Object queryGroupBy(@PathVariable String index,@PathVariable String groupByField,@PathVariable(required = false) Integer size) throws IOException {
        return  elasticsearchUtil.queryGroupBy(index,groupByField,size);
    }

    @GetMapping("/getTermFreq/{indexName}/{fieldName}/{docId}")
    @ApiOperation(value = "统计单个文档内某个字段中词频")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "indexName",paramType = "path",value = "索引名称",required = true),
            @ApiImplicitParam(name = "fieldName",paramType = "path",value = "类型字段",required = true),
            @ApiImplicitParam(name = "docId",paramType = "path",value = "文档ID",required = false)
    })
    public List<Map<String, Object>> getWordFrequency(@PathVariable String indexName, @PathVariable String fieldName, @PathVariable String docId) throws IOException {
        return  elasticsearchUtil.getWordFrequency(indexName, fieldName, docId);
    }



}
